#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include "myrandom.h"
#include "va.h"
#include "shop.h"

#define INF  999999.0
#define PRICE 2.0
#define GEO 0.4
#define CLIENT 1000
#define C_LAMBDA 20.0

static double c(int y); /*funcion de costo*/
static double f_lambda(double t); /*funcion de intensidad para PPNH*/
static int min(int x, int y);
static int max(int x, int y);

answer shop(unsigned int s, unsigned int S, double lambda,unsigned int x, double h, double L,double T,unsigned int n_h){
	
	double C = 0.0; /*Cantidad total de costos de los pedidos*/
	double H = 0.0; /*Cantidad total de costos de mantenimiento de inventario*/
	double R = 0.0; /*Cantidad total de ingresos obtenidos*/
	double  t0 =  E(lambda); /*Llegada primer cliente*/
	double t1 = INF;
	double t = 0.0,u=0.0;
	unsigned int i = 0, D = 0, y = 0, sold_prod = 0, sold_not_prod = 0, w = 0,flag=0, est = 0;
	answer res = calloc(1, sizeof(struct answers));

	if(T==0.0) /*estimamos mas o menos la cantidad de geometricas a generar*/
		est = 1000;
	else
		est = 5*(int)lambda*(int)T; /*agrego un poco mas para estar seguros*/
	
	res -> geom = calloc(est ,sizeof(double)); 
	res -> arrive = calloc(est,sizeof(double));
	res->a_geom = 0;
	res->a_arrive = 0;
	
	
	while((T == 0.0 && i < CLIENT) || (T!=0.0 && (t0<T || t1<T))){
		
		if(t0 < t1){
			H = H + (t0 - t)*((double)x)*h;
			t = t0;
			
			if(n_h == 1){ 
				u = (1.0/(float)ULONG_MAX) * mzran13();
				if(u < f_lambda(t)/C_LAMBDA)
					flag=1;
			}
			if(n_h==0 || flag==1){
				flag = 0;
				
				D  = G(GEO);
				res->geom[res->a_geom] = D;
				res->arrive[res->a_arrive] = t;
				res->a_geom++;
				res->a_arrive++;
			
				w = min(D,x);
				sold_prod = sold_prod + w;
				sold_not_prod = sold_not_prod + max(0, D-x);
				R = R + ((double)w)*PRICE;
				x = x-w;
			
				if( x < s && y == 0){
					y = S-x;
					t1 = t + L;
				}
				
				i++;
			}
			
			t0 = t + E(lambda);
		}
		else{

			H = H + (t1 -t)*((double)x)*h;
			t = t1;
			C = C + c(y);
			x = x + y;
			y = 0;
			t1 = INF;
		}
	}
	
	res->n = i;
	res-> sold_prod = sold_prod;
	res-> sold_not_prod = sold_not_prod;
	res->g = R-C-H;

	return res;
}

int destroy_shop(answer shop){
  
	free(shop->geom);
	free(shop->arrive);
	free(shop);
	shop = NULL;
	
	return 0;
}

static double c(int y){
	
	return y + (1.0/(double)y);
}

static double f_lambda(double t){
	
	return (-1.0/10.0)*pow(t-12.0,2) + 20;
}

static int min(int x, int y){
	if (x < y) return x;
	else return y;
}

static int max(int x, int y){
	if ( x <= y) return y;
	else return x;
}

